package demo.icanci.annotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 *
 * 解析注解
 * 
 * 注解的工作原理
 * - 通过键值对形式为注解属性赋值
 * - 编译器检查注解的使用范围，将注解信息写入元素属性表
 * - 运行的时候JVM将RUNTIME的所有注解都取出来最终存到map里面
 * - 创建AnnotationInvocationHandler实例并传入前面的map
 * - JVM动态代理为注解生成代理类，并初始化处理器
 * - 调用invoke方法，通过传入的方法名返回注解对应的属性值
 *
 * @author icanci
 * @date Created in 2021/02/05 01:05
 * @version 1.0
 */
public class AnnotationParse {

    /**
     * 解析类的注解
     */
    public static void parseTypeAnnotation() throws Exception {
        Class clazz = Class.forName("demo.icanci.annotation.IcanciCourse");
        Annotation[] annotations = clazz.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
            if (annotation instanceof CourseInfoAnnotation) {
                CourseInfoAnnotation courseInfoAnnotation = (CourseInfoAnnotation) annotation;
                System.out.println(courseInfoAnnotation.courseName());
                System.out.println(courseInfoAnnotation.courseIndex());
                System.out.println(courseInfoAnnotation.courseTag());
                System.out.println(courseInfoAnnotation.courseProfile());
            } else {
                continue;
            }
        }
    }

    /**
     * 解析成员变量上的注解
     */
    public static void parseFieldAnnotation() throws Exception {
        Class<?> clazz = Class.forName("demo.icanci.annotation.IcanciCourse");
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            declaredField.isAnnotationPresent(PersonInfoAnnotation.class);
            Annotation[] annotations = declaredField.getAnnotations();
            for (Annotation annotation : annotations) {
                if (annotation instanceof PersonInfoAnnotation) {
                    PersonInfoAnnotation personInfoAnnotation = (PersonInfoAnnotation) annotation;
                    System.out.println(personInfoAnnotation.age());
                    System.out.println(personInfoAnnotation.gender());
                    System.out.println(Arrays.toString(personInfoAnnotation.language()));
                } else {
                    continue;
                }
            }
        }
    }

    /**
     * 解析方法上的注解
     * @throws Exception
     */
    public static void parseMethodAnnotation() throws Exception {
        Class<?> clazz = Class.forName("demo.icanci.annotation.IcanciCourse");
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            if (declaredMethod.isAnnotationPresent(CourseInfoAnnotation.class)) {
                Annotation[] annotations = declaredMethod.getAnnotations();
                for (Annotation annotation : annotations) {
                    if (annotation instanceof CourseInfoAnnotation) {
                        CourseInfoAnnotation courseInfoAnnotation = (CourseInfoAnnotation) annotation;
                        System.out.println(courseInfoAnnotation.courseName());
                        System.out.println(courseInfoAnnotation.courseIndex());
                        System.out.println(courseInfoAnnotation.courseTag());
                        System.out.println(courseInfoAnnotation.courseProfile());
                    } else {
                        continue;
                    }
                }
            }
        }
    }

    public static void main(String[] args) throws Exception {
        parseTypeAnnotation();
        parseFieldAnnotation();
        parseMethodAnnotation();
    }
}
